package com.yanqu.road.server.manager.grandchild;

import com.yanqu.road.entity.grandchild.GrandChildChampion;
import com.yanqu.road.entity.grandchild.GrandChildChampionRankListModel;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.bussiness.grandchild.GrandChildBussiness;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.sort.GrandChildChampionSort;
import com.yanqu.road.pb.grandchild.GrandChildProto;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class GrandChildRankMgr extends TempMgr {

    // 区服ID，玩家ID，科举数据
    private static Map<Long, Map<Long, GrandChildChampion>> championMap;

    // 榜单
    private static Map<Integer, GrandChildChampionRankListModel> rankListModelMap = new ConcurrentHashMap<>();

    /**
     * 榜单最大长度
     */
    public static int getMaxRank() {
        return 100;
    }

    /**
     * 获取榜单
     */
    public static GrandChildProto.GrandChildGetChampionRankRespMsg.Builder getRankListMsg(long serverId, long userId) {
        int myRank = -1;

        RankProto.RankListMsg.Builder rankBuilder = RankProto.RankListMsg.newBuilder();

        int id = GrandChildExamConfigMgr.getGroupId(serverId);
        GrandChildChampionRankListModel rankListModel = getRankListModel(id, false);
        int rank = 0;
        for (GrandChildChampion champion : rankListModel.getRankList()) {

            rank++;
            if (champion.getUserId() == userId) {
                myRank = rank;
            }

            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(champion.getUserId());
            if (userBaseInfo == null) {
                userBaseInfo = new UserBaseInfo();
            }

            RankProto.RankTempMsg.Builder tmp = RankProto.RankTempMsg.newBuilder();
            tmp.setUserId(champion.getUserId());
            tmp.setValue(champion.getCount() + "");
            tmp.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            rankBuilder.addRankList(tmp);
        }


        GrandChildProto.GrandChildGetChampionRankRespMsg.Builder builder = GrandChildProto.GrandChildGetChampionRankRespMsg.newBuilder();
        builder.setMyCount(getGrandChildChampion(serverId, userId).getCount());
        builder.setMyRank(myRank);
        builder.setRankList(rankBuilder);
        return builder;
    }

    /**
     * 获取榜单
     *
     * @param forceRefresh 强制刷新
     */
    public static GrandChildChampionRankListModel getRankListModel(int groupId, boolean forceRefresh) {

        if (!forceRefresh && rankListModelMap.containsKey(groupId)) {
            return rankListModelMap.get(groupId);
        }

        synchronized (rankListModelMap) {

            if (!forceRefresh && rankListModelMap.containsKey(groupId)) {
                return rankListModelMap.get(groupId);
            }

            GrandChildChampionRankListModel model = new GrandChildChampionRankListModel(groupId, getMaxRank(), new GrandChildChampionSort());

            List<Long> id = GrandChildExamConfigMgr.getServerList(groupId);
            List<GrandChildChampion> total = new ArrayList<>();
            for (long serverId : id) {
                Map<Long, GrandChildChampion> serverMap = championMap.getOrDefault(serverId, new ConcurrentHashMap<>());
                total.addAll(
                        serverMap.values().stream().filter(item -> item.getCount() > 0).sorted(Comparator.comparing(GrandChildChampion::getCount).reversed()).limit(getMaxRank() + 10).collect(Collectors.toList())
                );
            }
            model.setRankList(total);

            rankListModelMap.put(groupId, model);

            return rankListModelMap.get(groupId);
        }
    }

    /**
     * 变更状元数量
     */
    public static void championCountChange(long serverId, long userId, long count) {
        GrandChildChampion champion = getGrandChildChampion(serverId, userId);
        // 变更值
        champion.changeCount(count);
        // 变更榜单
        rankChange(champion);
    }

    /**
     * 获取状元数量数据
     */
    public static GrandChildChampion getGrandChildChampion(long serverId, long userId) {
        if (!championMap.containsKey(serverId)) {
            synchronized (championMap) {
                if (!championMap.containsKey(serverId)) {
                    championMap.put(serverId, new ConcurrentHashMap<>());
                }
            }
        }
        Map<Long, GrandChildChampion> map = championMap.get(serverId);

        if (!map.containsKey(userId)) {
            synchronized (map) {
                if (!map.containsKey(userId)) {
                    GrandChildChampion data = new GrandChildChampion();
                    data.setServerId(serverId);
                    data.setUserId(userId);
                    data.setCount(0);
                    data.setUpdateTime(System.currentTimeMillis());
                    data.setInsertOption();
                    map.put(userId, data);
                }
            }
        }
        return map.get(userId);
    }

    /**
     * 分组榜单变更
     */
    public static void rankChange(GrandChildChampion champion) {
        int groupId = GrandChildExamConfigMgr.getGroupId(champion.getServerId());
        GrandChildChampionRankListModel rankListModel = getRankListModel(groupId, false);
        rankListModel.rankChange(champion);
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        // 科举状元数据
        championMap = GrandChildBussiness.getGrandChildChampionMap();

        // 榜单刷新
        for (int groupId : GrandChildExamConfigMgr.getGroupServerMap().keySet()) {
            getRankListModel(groupId, true);
        }
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    @Override
    public boolean save() {
        if (championMap != null) {
            for (Map<Long, GrandChildChampion> value : championMap.values()) {
                for (GrandChildChampion champion : value.values()) {
                    if (champion.isInsertOption()) {
                        GrandChildBussiness.addGrandChildChampion(champion);
                    } else if (champion.isUpdateOption()) {
                        GrandChildBussiness.updateGrandChildChampion(champion);
                    }
                }
            }
        }
        return true;
    }
}
